# -*- coding: utf8 -*-

import socket
from multiprocessing import Process
import subprocess
from datetime import datetime
import time
import traceback
from multiprocessing import Queue
import fcntl
import struct
import logging
def get_ip_address(ifname, ip_group):
    global inet,machine_code
    for index, enp in enumerate(ifname):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            inet = fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', bytes(enp[:15], 'utf-8')))
            if socket.inet_ntoa(inet[20:24]) in list(ip_group.keys()):
                machine_code = ip_group[socket.inet_ntoa(inet[20:24])]
                break
        except socket.error:
            pass
    if not machine_code:
        machine_code = 'A0000'
    return machine_code
process_queue = Queue()
opc_logger = logging.getLogger('pojie_A10.producer_actual_values_A10')


class Receive_packets_process(Process):
    def __init__(self,queue,socket_TF,**kwargs):
        Process.__init__(self)
        self.queue = queue
        self.socket_TF = socket_TF
        if 'logger' in kwargs.keys():
            self.logger=kwargs['logger']
        else:
            self.logger=None
    def run(self):
        global sock
        is_first_collection = True
        socket_baocuo_jiange = []
        while self.socket_TF:
            if is_first_collection:
                try:
                    inter = "enp3s0"
                    sock = socket.socket(socket.PF_PACKET, socket.SOCK_DGRAM, socket.htons(0x0003))
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)  # 端口复用      True的作用是设置 SO_REUSEADDR 选项为启用状态，允许地址重用。
                    sock.bind((inter, 0))
                    sock.settimeout(30)  # 如果30秒没有接收到数据，就报错
                    if self.logger is not None:
                        self.logger.info("样本采集线程SampleProducer_actual_values_A10开始监听数据！！！")
                    is_first_collection = False
                except:
                    continue
            try:
                data, addr = sock.recvfrom(10240)
                self.queue.put(data)
            except:
                sock.close()
                is_first_collection = True
                time.sleep(5)
                if self.logger is not None:
                    self.logger.info(traceback.format_exc())
                # 会出现socket接收不到数据的情况，如果重启python就可以接收到数据了。这里进行一些处理
                # 10个数据，大概是六七分钟左右，长达七分钟接收不到数据，就需要进行重启。七分钟是随意的，这个时间不长也不短。
                if len(socket_baocuo_jiange) < 10:  # 不到10个数据就只添加，不做处理
                    socket_baocuo_jiange.append(datetime.now())
                    with open("//var//log//python_zhengchang_chongqi_jilu.log", "a+") as f:
                        f.write(f'{datetime.now()},{str(len(socket_baocuo_jiange))},{traceback.format_exc()}' + '\n')
                else:
                    socket_baocuo_jiange.pop(0)  # 保持长度为10。如果在10条数据之内，socket正常了，就不会执行重启，列表中的数据不会被清除掉。下次再报异常，会积累，所以要pop
                    socket_baocuo_jiange.append(datetime.now())
                    # 进行判断并重启
                    difference_in_seconds = socket_baocuo_jiange[-2] - socket_baocuo_jiange[-3]
                    if difference_in_seconds.total_seconds() < 120:  # 如果最近的第二、三条记录时差小于120秒
                        if (socket_baocuo_jiange[-1] - socket_baocuo_jiange[-3]).total_seconds() < 240:  # 如果最近的第一、三条记录时差小于240秒
                            # 两个时差都满足时，说明最近的超时记录是最新的
                            if self.logger is not None:
                                self.logger.info('socket长时间接收不到数据，执行了重启')
                            with open("//var//log//python_zhengchang_chongqi_jilu.log", "a+") as f:
                                f.write(f'{datetime.now()},socket长时间接收不到数据，执行了重启' + '\n')
                            subprocess.Popen(["bash", '/home/whhd/start.sh'])  # 开启一个新的进程进行重启
                            # 考虑增加一个检测python项目的脚本，用于保证只有一个项目在运行


p = Receive_packets_process(process_queue, True, logger=opc_logger)
p.daemon = True
p.start()